# (C) Datadog, Inc. 2018-present
# All rights reserved
# Licensed under a 3-clause BSD style license (see LICENSE)
import os
import sys
from urllib.response import addinfourl

import pytest

from datadog_checks.dev.conditions import CheckCommandOutput, CheckDockerLogs, CheckEndpoints, WaitFor
from datadog_checks.dev.errors import RetryError
from datadog_checks.dev.subprocess import run_command

from .common import not_windows_ci

try:
    from unittest import mock  # Python 3
except ImportError:
    import mock  # Python 2

HERE = os.path.dirname(os.path.abspath(__file__))
DOCKER_DIR = os.path.join(HERE, 'docker')


class TestWaitFor:
    def test_no_error_no_result_success(self):
        assert WaitFor(lambda: None)() is True

    def test_no_error_true_result_success(self):
        assert WaitFor(lambda: True)() is True

    def test_no_error_non_true_result_fail(self):
        with pytest.raises(RetryError):
            WaitFor(lambda: False, attempts=1)()

    def test_error_fail(self):
        def f():
            raise Exception

        with pytest.raises(RetryError):
            WaitFor(f, attempts=1)()


class TestCheckCommandOutput:
    def test_no_matches(self):
        check_command_output = CheckCommandOutput(
            [sys.executable, '-c', 'import os;print(\'foo\')'], ['bar'], attempts=1
        )

        with pytest.raises(RetryError):
            check_command_output()

    def test_matches(self):
        check_command_output = CheckCommandOutput([sys.executable, '-c', 'import os;print(\'foo\')'], ['foo', 'bar'])

        matches = check_command_output()
        assert matches == 1

    def test_matches_all_fail(self):
        check_command_output = CheckCommandOutput(
            [sys.executable, '-c', 'import os;print(\'foo\')'], ['foo', 'bar'], matches='all', attempts=1
        )

        with pytest.raises(RetryError):
            check_command_output()

    def test_matches_all_success(self):
        check_command_output = CheckCommandOutput(
            [sys.executable, '-c', 'import os;print(\'foobar\')'], ['foo', 'bar'], matches='all'
        )

        matches = check_command_output()
        assert matches == 2


class TestCheckDockerLogs:
    pytestmark = [not_windows_ci]

    def test_no_matches(self):
        compose_file = os.path.join(DOCKER_DIR, 'test_default.yaml')
        run_command(['docker', 'compose', '-f', compose_file, 'down'])
        check_docker_logs = CheckDockerLogs(compose_file, 'Vault server started', attempts=1)

        with pytest.raises(RetryError):
            check_docker_logs()

    def test_matches(self):
        compose_file = os.path.join(DOCKER_DIR, 'test_default.yaml')
        check_docker_logs = CheckDockerLogs(compose_file, 'Vault server started')

        try:
            run_command(['docker', 'compose', '-f', compose_file, 'up', '-d'], check=True)
            check_docker_logs()
        finally:
            run_command(['docker', 'compose', '-f', compose_file, 'down'], capture=True)


class TestCheckEndpoints:
    def test_fail(self):
        check_endpoints = CheckEndpoints('https://google.microsoft', attempts=1)

        with pytest.raises(RetryError):
            check_endpoints()

    def test_success(self):
        mock_resp = mock.create_autospec(addinfourl)
        mock_resp.getcode.return_value = 200
        check_endpoints = CheckEndpoints(['https://test.com'], send_request=lambda *args, **kwargs: mock_resp)

        check_endpoints()
